DOS + VBI

← Zurück

Von breeze an Dietrich

Hello there o/

I wrote a few small utilities for XDOS and when they were finish run, back to command line just fine. At this point I needed to use VBI and accordingly upon back to cli everything broke. It is logical to assume that upon return of control to XDOS, the VBI vector should be restored.

I tried to save values ​​from addresses $0222, $0223 but apparently they are intended for writing only. I tried to set these values ​​according to the documentation:

Normally jumps to the stage one VBLANK vector NMI interrupt processor at location 59345 ($E7D1); in the new OS "B" ROMs; 59310, $E7AE)

However, this also did not bring success.

The question is what VBI address needs to be set so that upon returning to XDOS it can continue working correctly and does this address match other DOS, for example Atari DOS 2.5?

Thank you in advance

Antworten

Hi breeze,

I'm not sure if I understand what you are trying to do: What do you mean with "everything broke"? So I can only do some guesses, what the problem may be:

For programs (and VBI) there are the same requirements with XDOS as for other DOS versions (except Sparta DOS, which does its own memory management). XDOS calls a COM/XEX program with JSR and this should return with RTS. Of course, when executing the RTS the 6502 stack must be at the same state as when executing the JSR. If you have for example a loop or your VBI takes to much time (more than 1 screen frame), the stack will roll over and thus the Atari crashes when executing RTS. Or you have simply overwriten the XDOS RAM area ($700 to $1DF0 in the standard configuration), which also will cause a crash when executing RTS.

It's not really neccessary to deactivate a VBI when returning to the XDOS CLI (or any other DOS version except Sparta DOS). But as you wrote, you are using VVBLKI=$222/3, which is time ciritical for SIO operations. This means, if VVBLKI takes more than around 300 CPU cycles, disk reads and writes won't work any more. For example, to avoid problems, the SIO routine SIOV=$E459 in the OS cuts the standard VVBLKI routine short by setting location CRITIC=$42 to 1. Also, the SIO routine in the OS uses CDTMA1=$226/7. If this is not handled by your VBI, the SIO won't handle disk timeouts any more. So it's a good idea to restore VVBLKI when returning to XDOS, but apart from SIO it's not neccessary.

Antworten

A crash when returning with RTS to XDOS CLI will also happen, if you use XIO 39/40 in your COM/XEX program. This is due to some tricks I used in XDOS to keep LOMEM low. If you use XIO 39/40, you can only return to XDOS CLI by using JMP (10), which is the same as using the BASIC command "DOS".

Antworten

Dietrich schrieb: I'm not sure if I understand what you are trying to do: What do you mean with "everything broke"?

By "everything is broken", I mean that there is no way to return to XDOS and continue working in the CLI. While waiting for your response, I did a lot of experiments and came to the conclusion that the problem is working with the keyboards call routine. I don't use XDOS when working with VBI, so there shouldn't be any problems there.

What's going on: 1) My program is loaded using XDOS. 2) Some block of data is loaded from disk using XDOS. 3) Setting VBI/DLI vectors:

  sei       // stop IRQ interrupts
  lda 0     // disable dli & vbi interrupt
  sta $D40E

  lda #lo(dli)    // set dli handler
  sta $0200
  lda #hi(dli)
  sta $0201

  ldy #lo(vbi)
  ldx #hi(vbi)    // load deferred vertical blank address
  lda #$07      // 7 = deferred, 6 = immediate
  jsr $E45C     // SETVBV

  lda #%11000000    // enable dli & vbi interrupt
  sta $D40E

  cli       //IRQ enabled

4) The program is running, no stack overload or cyclic calling of subprocedures. 5) Restore VBI vectors (documentations says that after powering on, the atari VBI looks at the address $e7b3):

  sei       // stop IRQ interrupts

  lda 0     // disable dli & vbi interrupt
  sta $D40E

  ldy #$b3
  ldx #$e7      // load deferred vertical blank address
  lda #7      // Command to reset vbi pointers.
  jsr $E45C     // SETVBV - Install vbi routine into interrupt chain.

  lda #%01000000    // enable vbi interrupt
  sta $D40E
  cli       //IRQ enabled

6) Exit

And nothing happens. The keyboard fell off and new commands cannot be entered in the CLI.

In one of the descriptions of working with VBI/DLI it was said that the problem is that the keyboard handler constantly polls the device and this can somehow be disabled, but I did not find how.

But here another question arises: during the program's operation, I poll the keyboard and wait for a key to be pressed, after which I exit the main loop. The question is how to make a correct initialization of VBI/DLI, then return it to how it was and calmly exit to XDOS.

I would be extremely grateful if you could give me a small example.

Antworten

OK, since you're calling SETVBV=$E45C with A=7, you are using deferred VBI (VVBLKD=$224/5), not immediate VBI (VVBLKI=$222/3).

1) There is a small bug in the code: It should read LDA #0:STA $D40E, not LDA 0:STA $D40E 2) Resetting VBI to $E7B3 is quite dangerous, since the default VBI address depends on the OS version in your Atari/emulator. For example, on the standard ATARI XL OS v2 it's $C28A. Better save VVBLKD=$224/5 and restore it from there. Or at least restore it from XITVBV+1=$E463/4 (XITVBV contains a JMP to the original VBI exit routine in all OS versions).

Apart form this, the code looks correct. So an example won't really help.

You can use another DOS and execute your program from there to see if it's a DOS dependend problem. Or to check for stack problems with RTS, don't return with RTS but JMP (10) - this restarts the XDOS CLI - the XDOS title should show up (JMP (10) works with every DOS - maybe except Sparta DOS).

Or if your program is not too long, send it to me and I'll take a look on it.

Antworten

Dietrich schrieb: Or if your program is not too long, send it to me and I'll take a look on it.

Thanks for your help and advice. I decided to write everything separately from scratch, without any extra code. And in principle, everything worked out very well. I even added DLI reinitialization and return to the initial state. Everything works fine even without the need for a jmp(10) transition.

Please take a look at what I have come up with and if there are no mistakes, than i can safely pass it off as a finished example.

Antworten

The code looks OK. Some remarks:

1) LDA $2F1:BEQ init:LDA 53769:init Reading 53769 doesn't change the keyboard status as the code suggests. According to the comment, you want to discard the last pressed key. This can be done by LDA #$FF:STA 764. 764 contains the last pressed key (in POKEY keyboard code) and when written to, the next read from the keyboard handler (for example the XDOS CLI or BASIC) will return the corresponding ATASCII char of the POKEY code in 764. The only reason for checking 53769 directly is, if the keyboard interrupt is disabled, since this interrupt transfers 53769 to 764 and also does keyboard debounce handling (using $2F1).

2) mainloop ... LDA $2F1:BEQ mainloop This should better be done with: mainloop ... LDA 764:CMP #$FF:BEQ mainloop Using $2F1 is quite unusual and may not work, if there are more than 3 frames between the last keypress and LDA $2F1.

3) _vbi PHA:STA $D40A Storing in WSYNC in VBI doesn't make sense. Perhaps you mean DLI.

Antworten

Dietrich schrieb: The code looks OK. Some remarks:

Thank you very much for your remarks, the code looks much better now.

The last question, perhaps not quite your field, but I see that you are not bad at understanding the features of atari and perhaps you can tell me what the problem might be.

When I was figuring out how to build a DisplayList for ANTIC, there were no particular problems, and in general I understood the principle of the commands. Most text modes, graphic chunks, and their combinations were displayed perfectly.

When it came to bitmap graphics and I tried to display the image in mic format, I encountered unexpected behavior. Somewhere after about a third of the screen, a forced reinitialization occurs (?) and the picture repeats from the beginning. It feels like there's an additional interruption and someone is rewriting the addresses.

16_.png

Then I tried to force the start address of the data for each DisplayList line and saw that there really is some garbage now.

15.png

Maybe this is some known problem and something needs to be disabled again using poke?

displayList:

  .ALIGN $0400

dlist
.byte $ce, scr, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $e, $e, $e, $e,$e,$e,$e,$e,$e,$e .byte $41, dlist

dli & vbi

_dli pha sta $D40A // WSYNC lda scr + 9600 sta 53274 // COLBAK lda scr + 9601 sta 53270 // COLPF0 lda scr + 9602 sta 53271 // COLPF1 lda scr + 9603 sta 53272 // COLPF2 lda scr + 9604 sta 53273 // COLPF3 pla rti

_vbi pha pla jmp $e462 // always exit deferred VBI with jump here

Thank you very much in advance

Antworten

This is quite easy to answer:

Since ANTIC's internal display data counter has only 12 bits, the display data can't cross a 4 KB boundary (without an LMS instruction), i.e. addresses $1000, $2000, $3000 and so on. For example, GRAPHICS 8 or 15 (ANTIC modes E and F) need 192*40 = 7680 bytes display data. So a 4 KB is crossed here always. To work around this, you need to reload the display data address with an LMS instruction (same as at start of the display list) just before crossing a 4 KB boundary. Try GRAPHICS 8 in BASIC and look at the created display list by the OS screen handler (SDLST=$230/1 points to it). You'll find a second LMS instruction, which ensures a 4 KB boundary isn't crossed.

In your second try, you do an LMS instruction every line. In this case, only the line where a 4 KB is crossed isn't displayed as desired.

Also, the display list itself can't cross a 1 KB boundary (ANTIC's internal display list counter has only 10 bits). In my programs I put the display lists just at the start of my XEX, so I have direct control over the assembled display list starting address.

Antworten

Dietrich schrieb: This is quite easy to answer:

Thank you very much for this useful information. I tried various combinations at random and that is why I periodically failed in one case or another.

If I understand correctly, it is better to place these images at the beginning, for example from the address $2000. Well, and make a list of DLI addresses in such a way that it does not cross the 4kb size.

Initially, I had suspicions that there was some kind of trick here and I decided to look at what the source code looks like, which is unloaded by the graph2font graphic editor, but it is filled with a bunch of conventions, macros for different modes, and as a result it was very difficult to understand what was wrong.

The only thing I see now is that the macro that generates the table for DLI uses not quite even addresses with an offset of +$0140.

.MACRO ANTIC_PROGRAM dta $4e,a(:1+$0000),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0140),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0280),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$03C0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0500),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0640),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0780),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$08C0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0A00),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0B40),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0C80),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$0DC0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1000),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1140),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1280),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$13C0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1500),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1640),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1780),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$18C0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1A00),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1B40),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1C80),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$1DC0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$2000),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$2140),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$2280),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$23C0),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$2500),$e,$e,$e,$e,$e,$e,$e dta $4e,a(:1+$2640),$e,$e,$e,$e,$e,$e,$e dta $41,a(:2) .ENDM

And now it has become clear why this was done.

Thanks again so much for your help!

Antworten

breeze schrieb: If I understand correctly, it is better to place these images at the beginning (of a 4 K boundary), for example from the address $2000.

Yes, if you do this, you'll need to use an LMS instruction after 102 displayed lines, since 10240 = 4080 < 4096 = 4K (and 10340 = 4120 > 4K) Of course you can use more LMS instructions in the DL as your macro does. This allows more display data start addresses to use without problems.

Antworten

Dietrich schrieb: Yes, if you do this, you'll need to use an LMS instruction after 102 displayed lines, since 10240 = 4080 < 4096 = 4K (and 10340 = 4120 > 4K) Of course you can use more LMS instructions in the DL as your macro does. This allows more display data start addresses to use without problems.

Thanks again, everything worked out. 17.png

I did it a little differently. I used the DLI address list from the Graph2Font macro. And then loaded the MIC file in chunks of 3840, 3840, and 1924 bytes. Accordingly, the first block was loaded into the address $2000, the second into $3000 and the remainder into $4000.

As a result, everything stopped conflicting and showed a complete picture.

Once again, thank you so much for your patience and clarification of such subtle nuances.

Antworten